/*--
 * XmlExporter.cs: Exports a registry branch to an XML-formatted text file.
 *--
 * For more information, please visit the Registrar Project site:
 *   http://code.google.com/p/registrar/
 *--
 * (c) 2006 Christopher E. Granade.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; exactly version 2
 * of the License applies to this software.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 
using System;
using System.Collections.Generic;
using System.Xml;
using Microsoft.Win32;

namespace Registrar {
	
	
	public class XmlSerializer : IRegistrySerializer {
		
		private Dictionary<Type, string> typemns =
			new Dictionary<Type, string>();
		
		private const string
			namespaceURI = "urn:registry-xml";
			
		private XmlDocument xd;
		
		public void Import(string target) {
		
		}
		
		public void Export(RegistryKey rk, string target) {
			
			// Fill the type mnemomics.
			typemns.Add(typeof(string), "string");
			typemns.Add(typeof(int), "dword");
			typemns.Add(typeof(byte[]), "hex");
			
			// Start making the XML document and its root element.
			xd = new XmlDocument();
			XmlElement root = xd.CreateElement(
				"registry-branch", namespaceURI);
			root.SetAttribute("base-path", rk.Name);
			
			xd.AppendChild(root);
			
			// Starting with the given registry key, recusively descend into the
			// branch and encode each part as XML elements.
			ExportKey(rk, root);
			
			xd.Save(target);
			
		}
		
		private string FormatValue(object o) {
			if (o is string) return (string) o;
			else if (o is int) return String.Format("{0:x8}", (int)o);
			else return "";
		}
		
		private void ExportKey(RegistryKey rk, XmlElement elem) {
			
			// For each subkey, create a new key element, and pass that
			// as a parent to this method.
			foreach (string kn in rk.GetSubKeyNames()) {
			
				XmlElement xe = xd.CreateElement("", "key", namespaceURI);
				elem.AppendChild(xe);
				xe.SetAttribute("name", kn);
				ExportKey(rk.OpenSubKey(kn), xe);
				
			}
			
			// Now process the values one by one.
			foreach (string vn in rk.GetValueNames()) {
			
				object o = rk.GetValue(vn);
				
				XmlElement xe = xd.CreateElement("", "value", namespaceURI);
				xe.InnerText = FormatValue(o);
				
				xe.SetAttribute("name", vn);
				xe.SetAttribute("type", typemns[o.GetType()]);
				
				elem.AppendChild(xe);
				
			}
			
		}
		
	}
	
}
